/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package Simulator;

import Common.*;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;

/**
 *
 * @author Scott
 */
public class SimulatorPassOne
{
    public String[] MEM = new String[1024];
    List<FileData> Records;
    boolean fatalError = false;

    public SimulatorPassOne (String file)
    {
        MEM = new String[1024];
        Records = new ArrayList<FileData>();
        try
        {
            BufferedReader in = new BufferedReader(new InputStreamReader(new FileInputStream(file)));
            while (in.ready() && !fatalError)
            {
                Records.add(GetRecord(in.readLine()));
            }
        } catch (FileNotFoundException ex)
        {
            // Error handling here
            ex.printStackTrace();
        } catch (IOException ex)
        {
            // Error handling here
            ex.printStackTrace();
        }
    }

    private FileData GetRecord(String line)
    {
        // Create a new FileData object and set the record line
        FileData result = new FileData(line);

        String[] columns = line.split(":");    // split on colon

        if (columns[0].equals("H") && columns.length == 11)
        {
            result.RecordType = "H";
            if(Utilities.ValidateLabel(columns[1]))
            {
                result.ModuleName = columns[1];
            }
            else
            {
                result.ModuleName = "Invalid";
                System.out.printf("Invalid Module Name. Module name must be a-z, A-Z, and 0-9 after the first character. 32 character max\n");
            }
            if(Utilities.ValidateHexRange(columns[2],0,0x03FF) && columns[2].length() == 4)
            {
                result.LoadAddress = columns[2];
            }
            else
            {
                result.LoadAddress = "0000";
                System.out.printf("Invalid load address. Must be a 4 digit hex number in the range 0 to 03FF (0 to 1023 decimal)\n");
            }
            if(Utilities.ValidateHexRange(columns[3],0,0x03FF) && columns[3].length() == 4)
            {
                result.StartAddress = columns[3];
            }
            else
            {
                result.StartAddress = "0000";
                System.out.printf("Invalid start address. Must be a 4 digit hex number in the range 0 to 03FF (0 to 1023 decimal)\n");
            }
            if(Utilities.ValidateHexRange(columns[4],0,0x03FF) && columns[4].length() == 4)
            {
                result.ModuleLength = columns[4];
                if((Integer.valueOf(result.LoadAddress, 16) + Integer.valueOf(result.ModuleLength, 16)) >= 0x400)
                {
                    fatalError = true;
                    System.out.printf("Memory Exceeded! Simulation halted.\n");
                }
            }
            else
            {
                try
                {
                    if((Integer.valueOf(result.LoadAddress, 16) + Integer.valueOf(columns[4], 16)) >= 0x400)
                    {
                        fatalError = true;
                        System.out.printf("Memory Exceeded! Simulation halted.\n");
                    }
                    else
                    {
                        result.ModuleLength = "0000";
                        System.out.printf("Invalid module length. Must be a 4 digit hex number in the range 0 to 03FF (0 to 1023 decimal)\n");
                    }
                }
                catch(NumberFormatException ex)
                {
                    result.ModuleLength = "0000";
                    System.out.printf("Invalid module length. Must be a 4 digit hex number in the range 0 to 03FF (0 to 1023 decimal)\n");
                }
                
                //result.ModuleLength = "0000";
                //System.out.printf("Invalid module length. Must be a 4 digit hex number in the range 0 to 03FF (0 to 1023 decimal)\n");
            }
            if(columns[5].length() == 16)
            {
                result.DateTime = columns[5];
            }
            else
            {
                result.DateTime = "1955301,22,00,00";   //default to bill gates' date of birth
                System.out.printf("Invalid Date/Time Format. Refer to the specifications on how to format Julian date/time\n");
            }
            if(Utilities.ValidateHexRange(columns[6],0,0x03FF) && columns[6].length() == 4)
            {
                result.TotalRecords = columns[6];
            }
            else
            {
                result.TotalRecords = "0000";
                System.out.printf("Invalid record count. Must be a 4 digit hex number in the range 0 to 03FF (0 to 1023 decimal)\n");
            }
            if(Utilities.ValidateHexRange(columns[7],0,0x03FF) && columns[7].length() == 4)
            {
                result.TextRecords = columns[7];
            }
            else
            {
                result.TextRecords = "0000";
                System.out.printf("Invalid text record count. Must be a 4 digit hex number in the range 0 to 03FF (0 to 1023 decimal)\n");
            }
            if(columns[8].length() == 7)
            {
                result.Assembler = columns[8];
            }
            else
            {
                result.Assembler = "AAA-AAA";
                System.out.printf("Invalid Assembler Name. Must be a 7 character string\n");
            }
            try
            {
                if(Integer.valueOf(columns[9], 10) <= 9999 && columns[9].length() == 4)
                {
                    result.AssemblerVersion = Integer.valueOf(columns[9]);
                }
                else
                {
                    result.AssemblerVersion = 0;
                    System.out.printf("Invalid version number. Must be a 4 digit integer in the range 0 - 9999\n");
                }
            }
            catch(NumberFormatException ex)
            {
                result.AssemblerVersion = 0;
                System.out.printf("Invalid version number. Must be a 4 digit integer in the range 0 - 9999\n");
            }
            if(Utilities.ValidateLabel(columns[10]))
            {
                result.ProgramName = columns[10];
            }
            else
            {
                result.ProgramName = "Invalid";
                System.out.printf("Invalid Program Name. Program name must be a-z, A-Z, and 0-9 after the first character. 32 character max\n");
            }
        }
        else if (columns[0].equals("T") && columns.length == 4)
        {
            result.RecordType = "T";
            if(Utilities.ValidateHexRange(columns[1],0,0x03FF) && columns[1].length() == 4)
            {
                result.Location = columns[1];
            }
            else
            {
                result.Location = "0000";
                System.out.printf("Invalid memory location. Must be a 4 digit hex number in the range 0 to 03FF (0 to 1023 decimal)\n");
            }
            if(Utilities.ValidateHexRange(columns[2],0,0xFFFF) && columns[2].length() == 4)
            {
                result.DataWord = columns[2];
            }
            else
            {
                result.DataWord = "0000";
                System.out.printf("Invalid instruction/data word. Must be a 4 digit hex code in the range 0 - FFFF\n");
            }
            if(Utilities.ValidateLabel(columns[3]))
            {
                result.ProgramName = columns[3];
            }
            else
            {
                result.ProgramName = "Invalid";
                System.out.printf("Invalid Program Name. Program name must be a-z, A-Z, and 0-9 after the first character. 32 character max\n");
            }
        }
        else if (columns[0].equals("E") && columns.length == 2)
        {
            result.RecordType = "E";
            if(Utilities.ValidateLabel(columns[1]))
            {
                result.ProgramName = columns[1];
            }
            else
            {
                result.ProgramName = "Invalid";
                System.out.printf("Invalid Program Name. Program name must be a-z, A-Z, and 0-9 after the first character. 32 character max\n");
            }
        }
        else    //load file format error
        {
            System.out.printf("Invalid Load File Format. Please check the specifications for correct record format.\n");
        }
        return result;
    }

    public void LoadMemory()
    {
        for (FileData r : Records)
        {
            if(r.RecordType.equals("T"))
            {
                MEM[Integer.valueOf(r.Location, 16)] = r.DataWord;
            }
        }
    }

    public void DisplayMem()
    {
        System.out.println();
        System.out.println("MEM Dump");
        System.out.printf("%-11s", "Location");
        System.out.printf("%-21s\n", "Instruction/Data Word");
        System.out.printf("%-11s", "--------");
        System.out.printf("%-21s\n", "---------------------");
        for(int i = 0; i < MEM.length; i++)
        {
            if(MEM[i] != null)
            {
                System.out.printf("%-11s", Utilities.IntTo4Hex(i));
                System.out.printf("%-21s\n", MEM[i]);
            }
        }
        System.out.println();
    }

}
